package scuts.io;


typedef FS = neko.FileSystem;

using scuts.Core;

import scuts.Core;
using scuts.monad.ArrayOptionMonad;
using scuts.monad.ArrayMonad;

typedef ProvideMonadFunctionsForUsing = scuts.monad.ArrayOptionMonad;

typedef FileInfo = String;

typedef FileMonad = Array<Option<FileInfo>>;

class FSQuery 
{
  
  public static function start(f:String):FileMonad 
  {
    return f.toArrayOption();
  }
  /*
  public static function toBottom(m:FileMonad):FileMonad 
  {
    filter(m, 
    function (file:String) {
      if FS.isDirectory();
    }
  }*/
  
  public static function filter (m:FileMonad, filter:String->Bool):FileMonad {
    return m.flatMap(
      function (file:String) {
        return if (filter(file)) file.toArrayOption() else [];
      }
    );
  }
  
  public static function select (m:FileMonad, ?filterFile:String->Bool, ?filterDir:String->Bool, ?recursive:Bool):FileMonad {
    filterFile = filterFile.orDefault(function (s) return true);
    filterDir = filterDir.orDefault(function (s) return true);
    recursive = recursive.orDefault(false);
    
    var f = function (s:String):Array<Option<String>> {
      var sub = [];

      if (try FS.isDirectory(s) catch (e:Dynamic) false && filterDir(s)) {
        
        if (recursive) {
          var subDirs = try FS.readDirectory(s) catch (e:Dynamic) [];
          

          var subs = select(subDirs.map(function (f) return Some(s + "/" + f)), filterFile, filterDir, recursive);
          for (s in subs) {
            sub.push(s);
          }
        }
        sub.push(Some(s));
      } else if (filterFile(s)) {
        
        sub.push(Some(s));
      }
      
      return sub;
    }
    return m.flatMap(f);
  }
  
  public static function delete (m:FileMonad):FileMonad {
    return m.flatMap(function (s) {
      if (FS.isDirectory(s))  {
        FS.deleteDirectory(s);
      } else {
        FS.deleteFile(s);
      }
      return [];
    });
  }
  
  
  
  public static function readDir (m:FileMonad):FileMonad {
    return m.flatMap((function (s) return try FS.readDirectory(s) catch (e:Dynamic) []).liftWithOption());
  }
  
  public static function filterDirs (m:FileMonad):FileMonad {
    return filter(m, (function (s) return try FS.isDirectory(s) catch (e:Dynamic) false));
  }
  
  public static function filterFiles (m:FileMonad):FileMonad {
    return filter(m, (function (s) return try FS.isDirectory(s) catch (e:Dynamic) false).not());
  }
  
  
  
}